import type Context from "../context/Context";
import { Bit, Fview } from "./UIDefine";
import type EventManage from "../event/EventManage";
import type BadgeManage from "../badge/BadgeManage";
import { Badge } from "../../module/common/BadgeType";
import Utils from "../utils/Utils";
import { SpineManage } from "../anim/SpineManage";
import SpineItem from "../anim/SpineItem";
import UIManage from "./UIManage";
import { Logger } from "../log/logger";
import PromiseReveal from "../utils/PromiseReveal";

export interface UIItemConstructor<T extends Fview> {
    new(): UIBase<T>;
}

export abstract class UIBase<T extends Fview, D = any> {

    public readonly view: T;
    public readonly data: D;
    public readonly name: string;
    public readonly __uuid__: number;

    //UI标识
    private _opened: boolean;
    private _bit: number = 0;
    private _closeWait: PromiseReveal<any>;

    //页面依赖动画
    private _skSign: number = 0;
    private _skArray: Map<string, SpineItem>;

    //监听列表
    protected eventListening: string[];

    //常用模块，方便调用
    protected readonly ui: UIManage;
    protected readonly evm: EventManage;
    protected readonly contex: Context;
    protected readonly badge: BadgeManage;
    protected readonly spine: SpineManage;

    constructor() {
        this.view = this.createView();
        this.name = Reflect.getPrototypeOf(this).constructor.name;
    }

    /**页面实例 */
    protected abstract createView(): T;

    /**实例后执行一次 */
    protected initialize?(): void;

    /**打开页面执行一次 */
    protected onOpen?(data?: D): void;

    /**页面置顶时调用 */
    protected onTop?(): void;

    /**关闭页面执行一次 */
    protected onClose?(reaskon?: any): void;

    /**销毁页面执行一次 */
    protected onDispose?(): void;

    /**每秒执行 */
    protected onLoopSecond?(): void;

    /**每帧执行 */
    protected onLoop?(): void;

    protected on(type: string, listener: Function, args?: any[]) {
        this.evm.on(type, this, listener, args);
    }

    protected once(type: string, listener: Function, args?: any[]) {
        this.evm.once(type, this, listener, args);
    }

    protected off(type: string, listener: Function) {
        this.evm.off(type, this, listener);
    }

    protected offAll() {
        this.evm.offAllCaller(this);
    }

    protected createSk(path: string, p: Fview = this.view, sign?: string) {
        let sk = this.spine.create(path);
        let skSign = sign || (++this._skSign).toString();
        // sk.addDisposeHandle(this, () => this._skArray && this._skArray.delete(skSign));
        sk.setP(p);
        let skArr = this._skArray || (this._skArray = new Map<string, SpineItem>());
        skArr.set(skSign, sk);
        return sk;
    }


    protected removeSk(skSign: string) {

        if (!this._skArray || !this._skArray.has(skSign)) {
            return;
        }

        this._skArray.get(skSign).disposeNow();
        this._skArray.delete(skSign);
    }


    /**
     * 添加红点监听
     * @param view 监听组件
     * @param type 
     * @param refresh 立即刷新一次红点
     */
    protected addBadge(view: Fview, type: Badge, refresh: boolean = true) {
        this.badge.on(type, view, this, refresh);
    }

    close(reson?: any) {
        this.ui.closeUI(this.__uuid__, reson);
    }

    writClose() {

        if (!this._closeWait) {
            this._closeWait = PromiseReveal.create();
        }
        return this._closeWait;
    }

    get opened() {
        return this._opened;
    }

    get disposed() {
        return this.__getBit(Bit.dispose);
    }


    //#region ==========内部调用==============

    /**
     * 内部调用
     * @private
     * @param reson 
     */
    private __open(reson: D) {
        if (this._opened) return;
        
        this._opened = true;

        if (!this.__getBit(Bit.initialize)) {
            this.__setBit(Bit.initialize);
            Utils.apply(this, "initialize");
        }
        console.log("打开页面", this.name);
        this.view.onClick(this, (e: Laya.Event) => e.stopPropagation());

        let listener = this.eventListening;
        if (listener && listener.length > 0) {
            listener.forEach(v => this[v] && this.on(v, this[v]))
        }

        Utils.apply(this, "onOpen", [reson]);
    }

    /**
     * 内部调用
     * @private
     * @param reson 
     */
    private __close(reson: any) {
        if (!this._opened) return;
        this._opened = false;

        this._closeWait && this._closeWait.resolve();
        Utils.apply(this, "onClose", [reson])

        this.offAll();
        this.badge.offAll(this);

        this._skSign = 0;
        let skarr = this._skArray;
        this._closeWait = null;

        if (skarr && skarr.size > 0) {
            skarr.forEach(v => v.disposeNow());
            skarr.clear();
        }
    }

    /**
     * 内部调用，生命周期由UIManage管理
     * @private
     * @returns 
     */
    private __dispose() {
        if (this.__getBit(Bit.dispose)) {
            return;
        }
        this.__setBit(Bit.dispose);

        Utils.apply(this, "onDispose");

        this.view.dispose();

        this._skArray = null;
        ["evm", "contex", "badge", "spine", "ui", "view", "data"].forEach(v => Reflect.deleteProperty(this, v));

        Logger.logView(this.name, "销毁页面");
    }

    private __getBit(bit: Bit) {
        return (this._bit & bit) !== 0;
    }

    private __setBit(bit: Bit) {
        this._bit = (this._bit | bit);
    }


    //#endregion
}
